package com.xbongbong.saas.help.workflow;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.pojo.ProductFieldPojo;
import com.xbongbong.paas.redis.RedisPrefixConstant;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ProductStockEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.StockFlowBillEntity;
import com.xbongbong.saas.domain.entity.ext.ProductEntityExt;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.help.BatchKeyHelp;
import com.xbongbong.saas.help.SaasFormHelp;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductStockModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.StockFlowBillModel;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 *
 * @author 魏荣杰
 *
 */
@Component
public class ProductValidateHelp {

    @Resource
    private SaasFormHelp saasFormHelp;
    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private ProductStockModel productStockModel;
    @Resource
    private AttrDecimalPrecisionHelper attrDecimalPrecisionHelper;
    @Resource
    private StockFlowBillModel stockFlowBillModel;
    @Resource
    private ProductModel productModel;

    /**
     * 获取分仓成本信息或者批次信息
     * @param productArray
     * @param warehouseId
     * @param corpid
     * @param costMap
     * @return
     * @throws XbbException
     */
    public Map<Object,Double> getSkuWarehouseOrBatchCost(JSONArray productArray, Long warehouseId, String corpid, Map<Object,Double> costMap, Map<Object,Double> stockMap) throws XbbException {


        List<String> batchList = new ArrayList<>();
        List<String> noBatchList = new ArrayList<>();
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject product = productArray.getJSONObject(i);
            Long pageProductId = product.getLong(SelectProductEnum.PRODUCT.getAttr());
            if (!StringUtil.isEmpty(product.getString(SelectProductEnum.BATCH.getAttr()))) {
                String batch;
                if (product.get(SelectProductEnum.BATCH.getAttr()) instanceof Map){
                    batch = product.getJSONObject(SelectProductEnum.BATCH.getAttr()).getString(StringConstant.VALUE);
                }else {
                    batch = product.getString(SelectProductEnum.BATCH.getAttr());
                }
                Long guaranteePeriod = product.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()) == null ? 0L : product.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY;
                batchList.add(BatchKeyHelp.getBatchKey(pageProductId, warehouseId, batch, product.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()), guaranteePeriod));
            }else {
                noBatchList.add(pageProductId + "_" + warehouseId);
            }
        }

        ProductFieldPojo costField = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_COST,ProductEnum.COST.getAttr(), corpid);
        ProductFieldPojo stockField = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_STOCK,ProductEnum.STOCK.getAttr(), corpid);
        Integer accuracy = costField.getAccuracy();
        Integer stockAccuracy = stockField.getAccuracy();

        costMap.put("costField", accuracy.doubleValue());

        if (!noBatchList.isEmpty()) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(ParameterConstant.CORPID, corpid);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put("warehouseKeyIn", noBatchList);
            List<ProductWarehouseEntity> productWarehouseEntities = productWarehouseModel.findEntitysWithWarehouseChecked(params, 1);
            for (ProductWarehouseEntity entity : productWarehouseEntities){
                costMap.put(entity.getWarehouseKey(), attrDecimalPrecisionHelper.setPrecision(entity.getCost(),accuracy));
                stockMap.put(entity.getWarehouseKey() + "_" + "" + "_" + 0 + "_" + 0,attrDecimalPrecisionHelper.setPrecision(entity.getNum(),stockAccuracy));
            }
        }

        //获取批次库存
        if (!batchList.isEmpty()) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("batchKeyIn", batchList);
            List<ProductStockEntity> entitys = productStockModel.findEntitys(param);
            for (ProductStockEntity item : entitys) {
                costMap.put(item.getBatchKey(), attrDecimalPrecisionHelper.setPrecision(item.getCost(), accuracy));
                stockMap.put(item.getBatchKey(), attrDecimalPrecisionHelper.setPrecision(item.getNum(), stockAccuracy));
            }
        }
        return costMap;
    }



    /**
     * 获取盘点单成本信息
     * @param productArray
     * @param warehouseId
     * @param corpid
     * @param costMap
     * @return
     * @throws XbbException
     */
    public Map<Object,Double> getInventorySkuWarehouseOrBatchCost(JSONArray productArray, Long warehouseId, String corpid, Map<Object,Double> costMap, Map<Object,Double> stockMap) throws XbbException {


        List<String> batchList = new ArrayList<>();
        List<String> noBatchList = new ArrayList<>();
        List<Long> productIdList = new ArrayList<>();
        for (int i = 0; i < productArray.size(); i++) {
            JSONObject product = productArray.getJSONObject(i);
            Long pageProductId = product.getLong(SelectProductEnum.PRODUCT.getAttr());
            productIdList.add(pageProductId);
            if (!StringUtil.isEmpty(product.getString(SelectProductEnum.BATCH.getAttr()))) {
                String batch;
                if (product.get(SelectProductEnum.BATCH.getAttr()) instanceof Map){
                    batch = product.getJSONObject(SelectProductEnum.BATCH.getAttr()).getString(StringConstant.VALUE);
                }else {
                    batch = product.getString(SelectProductEnum.BATCH.getAttr());
                }
                Long guaranteePeriod = product.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()) == null ? 0L : product.getLong(SelectProductEnum.GUARANTEE_PERIOD.getAttr()) * TimeConstant.SECONDS_PER_DAY;
                batchList.add(BatchKeyHelp.getBatchKey(pageProductId, warehouseId, batch, product.getLong(SelectProductEnum.PRODUCE_DATE.getAttr()), guaranteePeriod));
            }else {
                noBatchList.add(pageProductId + "_" + warehouseId);
            }
        }

        ProductFieldPojo costField = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_COST,ProductEnum.COST.getAttr(), corpid);
        ProductFieldPojo stockField = saasFormHelp.getProductFieldPojo(RedisPrefixConstant.PRODUCT_STOCK,ProductEnum.STOCK.getAttr(), corpid);
        Integer accuracy = costField.getAccuracy();
        Integer stockAccuracy = stockField.getAccuracy();

        costMap.put("costField", accuracy.doubleValue());

        if (!noBatchList.isEmpty()) {
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put(ParameterConstant.CORPID, corpid);
            params.put("del", DelEnum.NORMAL.getDel());
            params.put("warehouseKeyIn", noBatchList);
            List<ProductWarehouseEntity> productWarehouseEntities = productWarehouseModel.findEntitysWithWarehouseChecked(params, 1);
            for (ProductWarehouseEntity entity : productWarehouseEntities){
                costMap.put(entity.getWarehouseKey(), attrDecimalPrecisionHelper.setPrecision(entity.getCost(),accuracy));
                stockMap.put(entity.getWarehouseKey() + "_" + "" + "_" + 0 + "_" + 0,attrDecimalPrecisionHelper.setPrecision(entity.getNum(),stockAccuracy));
            }
        }

        // 循环找出没流水的产品
        List<Long> resetCostIdList = new ArrayList<>();
        for (Long productId : productIdList) {
            StockFlowBillEntity count = stockFlowBillModel.checkDate(corpid, 0L, Collections.singletonList(productId));
            // 如果没流水说明需要去产品的成本
            if (Objects.isNull(count)){
                resetCostIdList.add(productId);
            }
        }
        if (CollectionUtils.isNotEmpty(resetCostIdList)){
            List<ProductEntityExt> productList = productModel.getProductListByIdIn(corpid, resetCostIdList, 0);
            if (CollectionUtils.isNotEmpty(productList)){
                for (ProductEntityExt productEntityExt : productList) {
                    Long id = productEntityExt.getId();
                    JSONObject data = productEntityExt.getData();
                    if (Objects.nonNull(data) && Objects.nonNull(data.get(ProductEnum.COST.getAttr()))){
                        costMap.put(id + "_" + warehouseId, attrDecimalPrecisionHelper.setPrecision(data.getDouble(ProductEnum.COST.getAttr()),accuracy));
                    }
                }
            }
        }
        //获取批次库存
        if (!batchList.isEmpty()) {
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("batchKeyIn", batchList);
            List<ProductStockEntity> entitys = productStockModel.findEntitys(param);
            for (ProductStockEntity item : entitys) {
                costMap.put(item.getBatchKey(), attrDecimalPrecisionHelper.setPrecision(item.getCost(), accuracy));
                stockMap.put(item.getBatchKey(), attrDecimalPrecisionHelper.setPrecision(item.getNum(), stockAccuracy));
            }
        }

        return costMap;
    }
}
